package it.uniroma2.svd.writer;

import java.io.*;

public class LittleEndianOutputStream extends DataOutputStream
{

    protected int written;

    public void writeString(String string, int length)
        throws IOException
    {
        if(string.length() < length)
        {
            String newstring = zeroFill(string, length);
            byte bytes[] = newstring.getBytes();
            out.write(bytes);
        } else
        {
            String newstring = string.substring(0, length);
            byte bytes[] = newstring.getBytes();
            out.write(bytes);
        }
    }

    private String zeroFill(String string, int length)
    {
        char oldchars[] = string.toCharArray();
        char newchars[] = new char[length];
        for(int i = 0; i <= newchars.length - 1; i++)
            if(i <= oldchars.length - 1)
                newchars[i] = oldchars[i];
            else
                newchars[i] = '\0';

        return new String(newchars);
    }

    public LittleEndianOutputStream(OutputStream out)
    {
        super(out);
    }

    public void writeLEShort(short s)
        throws IOException
    {
        out.write(s & 0xff);
        out.write(s >>> 8 & 0xff);
        written += 2;
    }

    public void writeLEChar(int c)
        throws IOException
    {
        out.write(c & 0xff);
        out.write(c >>> 8 & 0xff);
        written += 2;
    }

    public void writeLEInt(int i)
        throws IOException
    {
        out.write(i & 0xff);
        out.write(i >>> 8 & 0xff);
        out.write(i >>> 16 & 0xff);
        out.write(i >>> 24 & 0xff);
        written += 4;
    }

    public void writeLELong(long l)
        throws IOException
    {
        out.write((int)l & 0xff);
        out.write((int)(l >>> 8) & 0xff);
        out.write((int)(l >>> 16) & 0xff);
        out.write((int)(l >>> 24) & 0xff);
        out.write((int)(l >>> 32) & 0xff);
        out.write((int)(l >>> 40) & 0xff);
        out.write((int)(l >>> 48) & 0xff);
        out.write((int)(l >>> 56) & 0xff);
        written += 8;
    }

    public final void writeLEFloat(float f)
        throws IOException
    {
        writeLEInt(Float.floatToIntBits(f));
    }

    public final void writeLEDouble(double d)
        throws IOException
    {
        writeLELong(Double.doubleToLongBits(d));
    }

    public void writeLEChars(String s)
        throws IOException
    {
        int length = s.length();
        for(int i = 0; i < length; i++)
        {
            int c = s.charAt(i);
            out.write(c & 0xff);
            out.write(c >>> 8 & 0xff);
        }

        written += length * 2;
    }

    public void writeLEUTF(String s)
        throws IOException
    {
        int numchars = s.length();
        int numbytes = 0;
        for(int i = 0; i < numchars; i++)
        {
            int c = s.charAt(i);
            if(c >= 1 && c <= 127)
            {
                numbytes++;
                continue;
            }
            if(c > 2047)
                numbytes += 3;
            else
                numbytes += 2;
        }

        if(numbytes > 65535)
            throw new UTFDataFormatException();
        out.write(numbytes >>> 8 & 0xff);
        out.write(numbytes & 0xff);
        for(int i = 0; i < numchars; i++)
        {
            int c = s.charAt(i);
            if(c >= 1 && c <= 127)
            {
                out.write(c);
                continue;
            }
            if(c > 2047)
            {
                out.write(0xe0 | c >> 12 & 0xf);
                out.write(0x80 | c >> 6 & 0x3f);
                out.write(0x80 | c & 0x3f);
                written += 2;
            } else
            {
                out.write(0xc0 | c >> 6 & 0x1f);
                out.write(0x80 | c & 0x3f);
                written++;
            }
        }

        written += numchars + 2;
    }
}
